#include "as-node-mem.h"
#include <malloc.h>
namespace tinyscript{
namespace internal{

void ASNodeMemoryPool::Grow() {
    void* header;
    void* buffer = malloc( sizeof(MempoolHeader) + grow_size_* object_size_ );
    if( buffer == NULL )
        return;
    header = buffer;
    MHeader(buffer)->next = NULL;
    buffer = BufferMove(buffer,sizeof(MempoolHeader));
    for( size_t i = 0 ; i < grow_size_-1 ; ++i ) {
        FHeader(buffer)->next = (FreelistHeader*)BufferMove(buffer,object_size_);
        buffer = BufferMove(buffer,object_size_);
    }
    FHeader(buffer)->next = NULL;

    if(pool_ == NULL) {
        pool_ = MHeader(header);
    } else {
        pool_->next = MHeader(header);
    }
    assert(header_==NULL);
    header_ = FHeader( BufferMove(header,sizeof(MempoolHeader) ) );
}

void ASNodeMemoryPool::Destroy() {
    MempoolHeader* temp;
    temp = pool_;
    while( pool_ ) {
        temp = pool_->next;
        free(pool_);
        pool_ = temp;
    }
}

ASNodeMemoryPool::ASNodeMemoryPool( size_t sz , size_t objsize ) {
    if( sz==0 )
        sz = 1;
    grow_size_ = sz;
    pool_ = NULL;
    header_ = NULL;
    object_size_ = objsize;
    Grow();
}

ASNodeMemoryPool::~ASNodeMemoryPool() {
    Destroy();
}

void* ASNodeMemoryPool::New() {
    if( header_ == NULL )
        Grow();
    if( header_ == NULL )
        return NULL;
    void* ret = header_;
    header_ = header_->next;
    return ret;
}

void ASNodeMemoryPool::Delete( void* ptr ) {
    if( header_ == NULL ) {
        header_ = FHeader(ptr);
        FHeader(ptr)->next=NULL;
    } else {
        FHeader(ptr)->next = header_;
        header_ = FHeader(ptr);
    }
}


}
}
